function [data, head] = getClipBoardData(dataURL)
%GETCLIPBOARDDATA downloads data from ZI server.
%   Press the 'Copy' button in the LabOne UI, and then run this command.
    L = log4m.getLogger;
    if nargin == 0
        dataURL = clipboad('paste');
    end
    dataStr = downloadData(dataURL);
    [head, bodyStr] = separateHeadBody(dataStr);

    switch head.module
        case {'Scope', 'Sweep'} % All variables share the same x-axis
            if head.nLine <= 4
                error('Error occured during reading the data. head.nLine <= 4');
            end
            nVariable = head.nLine - 3 - 1; nCol = nVariable + 1;
            L.info('getClipBoardData::getClipBoardData', sprintf('%d variable(s) detected.', nVariable));
            valueMat = bodyMat(bodyStr, nCol);
            data = arrayfun(@(k) mat2struct(valueMat, k), 2:nCol);
        case {'Spectrum', 'Plotter', 'DAQ'} % x-axis values of different variables may be different, even with different size.
            if mod(head.nLine - 3, 2) == 1
                error('Error occured during reading the data.');
            end
            nVariable = (head.nLine - 3)/2; nCol = 2;
            L.info('getClipBoardData::getClipBoardData', sprintf('%d Variable(s) detected.', nVariable));
            valueMat = bodyMat(bodyStr, nCol);
            [~, idx] = maxk(abs(diff(valueMat(:, 1))), nVariable-1);
            data = arrayfun(@(k1, k2) mat2struct(valueMat(k1:k2, :), 2), [1; sort(idx)+1], [sort(idx); size(valueMat, 1)]);
        otherwise
            error('Unknown module name [%s]', head.module);
    end
end

function dataStr = downloadData(dataURL)
    L = log4m.getLogger;
    try
        L.info('getClipBoardData::downloadData', sprintf('Downloading data from server [url = %s] ...', dataURL));
        dataStr = textscan(webread(dataURL), '%s', 'Delimiter', '\n');
        dataStr = dataStr{1};
        fprintf('\bDone.\n');
    catch
        error('Data downloading failed ID=[%s]. Please "Copy" data from LabOne UI first.', dataURL);
    end
    
end

function [head, body] = separateHeadBody(dataStr)
    head.nLine = count(cellfun(@(s) s(1), dataStr).', '%'); %number of head lines
    head.string = dataStr(1:head.nLine);

    m = regexp(head.string{1}, 'Spectrum|Sweep|Scope|Plotter|DAQ', 'match'); head.module = m{1};
    m = regexp(head.string{1}, '\w*$', 'match'); head.id = m{1};
    head.device = regexp(head.string{2}, 'DEV[0-9]*', 'match');
    
    datetimeReg='(\d{4})\/(0\d{1}|1[0-2])\/(0\d{1}|[12]\d{1}|3[01])\s+(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d';
    head.timestampe=datetime(regexp(head.string{3}, datetimeReg, 'match'));    
    body = dataStr(head.nLine+1:end);
end

function valueMat = bodyMat(bodyStr, nCol)
    L = log4m.getLogger;    
    formatStr =  repmat('%f',1, nCol); 
    nRow = size(bodyStr, 1);
    L.info('getClipBoardData::bodyMat', sprintf('Converting data size = [%d X %d] ...', nRow, nCol));
    valueMat = cell2mat(cellfun(@(s) cell2mat(textscan(s, formatStr, 'Delimiter', ';')),  bodyStr, 'UniformOutput', false));
    fprintf('\bDone.\n');
end

function data = mat2struct(mat, k)
    data.x = mat(:, 1);
    data.y = mat(:, k);
end